home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 09 - 1993 / 09.05 May 93 / AppleEvents 101 / AE101.c next >
Encoding:
Text File  |  1993-04-05  |  27.4 KB  |  1,115 lines  |  [TEXT/KAHL]

  1. // Source Code for AE101
  2. // Copyright 1993 
  3. // by Jeffrey B. Kane, MD
  4. /* put compile time flags here */
  5.  
  6. /* includes */
  7. #include <Script.h>
  8. #include <GestaltEqu.h>
  9. #include <AppleEvents.h>
  10. #include <PPCToolBox.h>
  11.  
  12. /* define */
  13. #define    true    1
  14. #define    false    0
  15. #define    boolean    int
  16. #define    SetRect(aRect,l,t,b,r) {(aRect)->top = (t);(aRect)->left = (l);(aRect)->bottom = (b);(aRect)->right = (r);}
  17.  
  18. /* constants */
  19. #define    kAppleMenuID     128    /* Apple Menu Resource ID */
  20. #define    kFileMenuID     129    /* File Menu Resource ID */
  21. #define    kEditMenuID     130    /* Edit Menu Resource ID */
  22. #define    kSpecialMenuID    131 /* Special Menu Resource ID */
  23. #define    kAboutBoxID        128    /* About box alert Resource ID */
  24. #define kErrorAlertID    129 /* Error Alert Box */
  25. #define kWindTemplateID    128    /* template for new windows */
  26. #define    cAboutItem        1
  27. #define    cNewItem         1
  28. #define    cOpenItem         2
  29. #define    cCloseItem         3
  30. #define    cQuitItem         5
  31. #define    cSendQuitItem        1
  32. #define    cSendNewItem        2
  33. #define    cSendCloseItem        3
  34. #define    cSendAboutItem        4
  35. #define    cSendAboutToFinder    6
  36. #define cSendEmptyTrashToFinder 7
  37. #define     kAENewWindow        'NEW '
  38. #define     kAECloseWindow      'clos'
  39. #define     kAEAbout            'abou'
  40. #define        kAEEmptyTrash        'empt'
  41. #define     kFndrEventClass     'FNDR'
  42.  
  43. /* prototypes */
  44. void    InitMac(int numMasters);
  45. void    Loop(void);
  46. void    DoMouseDown(EventRecord* theEvent);
  47. void    DoCloseWindow(void);
  48. void    DoNewWindow(void);
  49. void    SetUpMenus(void);
  50. void     DoMenu(EventRecord* theEvent,WindowPtr whichWindow,long selection);
  51. void    doAboutBox(void);
  52. void     DoKey(EventRecord* theEvent);
  53. void     DoUpdate(EventRecord* theEvent);
  54. void    DoOSEvent(EventRecord* theEvent);
  55. void    FixCursor(void);
  56. extern    pascal    OSErr doAEQuit(AppleEvent* theAppleEvent, AppleEvent* theReply, long handlerRefcon);
  57. extern    pascal    OSErr doAENew(AppleEvent* theAppleEvent, AppleEvent* theReply, long handlerRefcon);
  58. extern    pascal    OSErr doAEClose(AppleEvent* theAppleEvent, AppleEvent* theReply, long handlerRefcon);
  59. extern    pascal    OSErr doAEAbout(AppleEvent* theAppleEvent, AppleEvent* theReply, long handlerRefcon);
  60. OSErr    MissedRequiredParameters(AppleEvent* theAppleEvent);
  61. void    ConnectToFinder(void);
  62. void    DisconnectFromFinder(void);
  63. boolean    BitTest(long* aValue,int Bit);
  64. void    SetUpperCorner(Rect* theRect,Point aPt);
  65. void    GetUpperCorner(Rect* theRect,Point *aPt);
  66. void    SetLowerCorner(Rect* theRect,Point aPt);
  67. void    GetLowerCorner(Rect* theRect,Point *aPt);
  68. void    SendQuit(void); /* sending an AE Quit */
  69. void    SendNew(void); /* sending an AE New */
  70. void    SendClose(void); /* sending an AE Close */
  71. void    SendAbout(void);
  72. void    SendAboutToFinder(void);
  73. void    SendEmptyTrashToFinder(void);
  74. void    SendEvent(AEEventClass theAEEventClass, AEEventID theAEEventID,AEAddressDesc* theTargetAddressPtr);
  75. void    SendFndrEvent(AEEventID theAEEventID);
  76. void    SendCoreEvent(AEEventID theAEEventID);
  77. void     ErrorAlert(ConstStr255Param theString,OSErr theErr);
  78. void    CopyPStr(char* fromStr,char* toStr);
  79.  
  80. /* globals */
  81. boolean    gHasColor    = false;    /* does this machine support 32 bit quickdraw? */
  82. boolean     gProcessor    = 0;/* what microprocessor is this? */
  83. boolean        gHasAppleEvents = false;/* do we support IAC (Apple Events)? */
  84. boolean        gFinished    = false;    /* did the user want to quit? */
  85. boolean        gInForeground = true;/* are we running in the foreground *//* or background?                         */
  86. CursHandle    gPlusCursor = nil;/* data for the plus cursor */
  87. boolean        gHasPPCToolbox = false;
  88. RgnHandle    gMainContentRgn = nil;
  89. RgnHandle    gAllElseRgn = nil;    
  90. RgnHandle    gMouseMovedRgn = nil;
  91.  
  92. ProcessSerialNumber gFinderPSN = {0L,0L};
  93. TargetID    gFinderTargetID;
  94.  
  95. MenuHandle    AppleMenu    = nil;
  96. MenuHandle    FileMenu    = nil;
  97. MenuHandle    SpecialMenu    = nil;
  98. MenuHandle    EditMenu    = nil;
  99.  
  100. WindowPtr    gWindow        = nil;
  101. WindowRecord gWStorage;
  102.  
  103.  
  104. /* ================================= */
  105. boolean    BitTest(long* aValue,int Bit)
  106. {
  107.     asm {
  108.         clr.l    D0
  109.         clr.l    D2
  110.         move.l    aValue,A0
  111.         move.l    (A0),D1
  112.         move.w    Bit,D2
  113.         btst.l    D2,D1
  114.         beq.s    @1
  115.         moveq.l    #1,D0
  116.     @1
  117.     }
  118.  
  119. }
  120. /* actual code */
  121.  
  122. /* ================================= */
  123. void    CopyPStr(char* fromStr, char* toStr)
  124. {
  125.     short    i = 0;
  126.  
  127.     for (i=0; i <= (fromStr[0]); i++) 
  128.     {toStr[i] = fromStr[i];}
  129. } /* CopyPStr */
  130.  
  131. /* ================================= */
  132. void    ConnectToFinder(void)
  133. {
  134.     OSErr            theErr;
  135.     PortInfoRec        thePortInfo;
  136.     LocationNameRec    theLocationNameRec;
  137.     
  138.     /* find out who's available     *//* (kinda like dating)             */
  139.     thePortInfo.authRequired = false;
  140.     thePortInfo.name.nameScript = smRoman; /* english */
  141.     thePortInfo.name.portKindSelector = ppcByString;
  142.     CopyPStr((char*)"\pOscar",(char*)thePortInfo.name.name);
  143.  
  144.     theLocationNameRec.locationKindSelector = ppcNoLocation; /* local machine */
  145.     // since we just stated we are on our // own machine, we don't need to fill //anything else out    
  146.  
  147.     theErr = PPCBrowser((ConstStr255Param)"\pLocate the Finder and click on it",
  148.                         nil,
  149.                         false, /* we are not Specifing a default to find */
  150.                         &theLocationNameRec,
  151.                         &thePortInfo,
  152.                         nil,
  153.                         nil);    
  154.                         /* use the default */
  155.                         
  156.    /* construct a targetID from the data provided */
  157.     gFinderTargetID.sessionID = 0; /* we haven't opened a session yet */
  158.     
  159.      /* the PPCBrowser's PPCPortRec *//* Returned */
  160.     BlockMove(&(thePortInfo.name),&(gFinderTargetID.name),sizeof(PPCPortRec));
  161.     gFinderTargetID.location = theLocationNameRec; /* the PPCBrowser's                 *//* LocationNameRec returned     */
  162. //    the system will fill in the recvrName 
  163. //    and sesionID after we make a connection
  164. //    we can use them later to speed up
  165. //    AESend
  166.     
  167.     if (theErr != noErr) ErrorAlert((ConstStr255Param)"\pBrowser Result Bad: ",theErr);    
  168.     else 
  169.     {    
  170.         // This is only valid because we are     // on a local machine, you have to     // use TragetID or SessionIDs if you 
  171.         //are connecting out on the network 
  172.  
  173.         theErr = GetProcessSerialNumberFromPortName((PPCPortPtr)(&(thePortInfo.name)),
  174.     (ProcessSerialNumberPtr)(&gFinderPSN));
  175.         if (theErr != noErr)
  176.         { ErrorAlert(        (ConstStr255Param)"\pError             getting Process Serial                     Number",theErr);
  177.         }
  178.     } /* else */
  179.     
  180.     /* start communications */
  181.  
  182. } /* ConnectToFinder */
  183.  
  184. /* ================================= */
  185. void    DisconnectFromFinder(void)
  186. {
  187.     OSErr                theErr;
  188.     PPCClosePBRec    thePPCClosePBRec;
  189.     PPCEndPBRec        thePPCEndPBRec;
  190.     
  191. }    /* DisconnectFromFinder */
  192.  
  193.  
  194.  
  195. /* ================================= */
  196. void    InitMac(int numMasters)
  197. {
  198.     int        i;
  199.     long    response = 0L;
  200.     OSErr    theErr;
  201.     PScrapStuff theScrapStuff;
  202.     
  203.     // set a few enviromental globals that 
  204.     // will be handy later
  205.     
  206.     theErr = Gestalt(gestaltQuickdrawFeatures,&response);
  207.     if (BitTest(&response,     gestaltHasColor)) gHasColor = true;
  208.     
  209.     theErr = Gestalt(    gestaltProcessorType,&response);
  210.     gProcessor = response;
  211.     
  212.     theErr = Gestalt(    gestaltAppleEventsAttr, &response);
  213.     if (BitTest(&response,     gestaltAppleEventsPresent))     gHasAppleEvents = true;
  214.     
  215.     // see if we need to initalize the PPC 
  216.     // toolbox 
  217.  
  218.     theErr = Gestalt(    gestaltPPCToolboxAttr,&response);
  219.     if (theErr == noErr)
  220.     {
  221.         gHasPPCToolbox = true; // if no error was returned we have a 
  222.     // PPC toolbox
  223.         if (BitTest(&response, gestaltPPCSupportsRealTime) != 0)
  224.             theErr = PPCInit(); //    if this bit is not set, we need to //    intialize
  225.             
  226.     //    You can add your own alert in 
  227.     //response to the following PPC tests 
  228.         if (BitTest(&response, gestaltPPCSupportsOutGoing) != 0);
  229.             // Tell the User to turn on 
  230.             // AppleTalk in the Chooser
  231.         if (BitTest(&response, gestaltPPCSupportsIncoming) != 0);
  232.             // Tell the User to activate 
  233.             // file sharing or AppleTalk (in 
  234.             // the chooser)
  235.         
  236.     }
  237.         
  238.     
  239.     gPlusCursor = GetCursor(plusCursor);
  240.     if (gPlusCursor) 
  241.         {
  242.         MoveHHi((Handle)gPlusCursor);
  243.         HLock((Handle)gPlusCursor);
  244.         }
  245.     
  246.     /* now initialize the program itself */
  247.     
  248.     InitGraf(&thePort);
  249.     InitFonts();
  250.     InitMenus();
  251.     InitWindows();
  252.     InitDialogs(nil);
  253.     TEInit();
  254.     InitCursor();
  255.     for (i=1; i > numMasters; i++) MoreMasters();
  256.     
  257.     /* if we have IAC capability, install the AE handler */
  258.     if (gHasAppleEvents)
  259.     {
  260.     theErr = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
  261.                                    (ProcPtr)doAEQuit, 0L, false);
  262.                                    
  263.     theErr = AEInstallEventHandler(kCoreEventClass, kAENewWindow,
  264.                                    (ProcPtr)doAENew, 0L, false);
  265.                                    
  266.     theErr = AEInstallEventHandler(kCoreEventClass, kAECloseWindow,
  267.                                    (ProcPtr)doAEClose, 0L, false);
  268.                                    
  269.     theErr = AEInstallEventHandler(kCoreEventClass, kAEAbout,
  270.                                    (ProcPtr)doAEAbout, 0L, false);
  271.  
  272.     } /* gHasAppleEvents */
  273.     
  274.     /* create the regions to check our mouse against */
  275.     gMainContentRgn = NewRgn();
  276.     gAllElseRgn = NewRgn();    
  277.     CopyRgn(GetGrayRgn(),gMainContentRgn);
  278.     gMouseMovedRgn = gAllElseRgn; /* we are initially in an empty desktop */
  279.  
  280.     
  281.     /* Deal with the scrap */
  282.     theScrapStuff = InfoScrap();
  283.     theErr = ZeroScrap();
  284.     {
  285.     char        tempScrap[] = "More Stuff";
  286.     PicHandle    tempPict = nil;
  287.     Rect        tempRect = { -5000,-5000,-4800,-4800 }; /* off screen */
  288.     long        scrapSize = 0;
  289.     Ptr            thePtr = nil;
  290.     CWindowRecord theWStorage;
  291.     WindowPtr    tempWind = nil;
  292.     
  293.     OffsetRect(&tempRect,5050,5050);
  294.     tempWind = NewCWindow(&theWStorage, &tempRect, &"\p", true, plainDBox, (Ptr)(-1), false, 0);
  295.     SetPort(tempWind);
  296.     ClipRect(&(tempWind->portRect));
  297.     ForeColor(greenColor);
  298.     tempRect.left = 0;
  299.     tempRect.top = 0;
  300.     tempRect.right = 100;
  301.     tempRect.bottom = 20;
  302.     tempPict = OpenPicture(&tempRect);
  303.     TextSize(14);
  304.     TextFace(bold | italic);
  305.     TextBox(tempScrap,sizeof(tempScrap),&tempRect,teJustCenter);
  306.     TextFace(0);
  307.     TextSize(12);
  308.     ClosePicture();
  309.     HLock((Handle)tempPict);
  310.     scrapSize = GetHandleSize((Handle)tempPict);
  311.     thePtr = (Ptr)(*tempPict); 
  312.     theErr = PutScrap(scrapSize,'PICT',thePtr);
  313.     HUnlock((Handle)tempPict);
  314.     KillPicture(tempPict);
  315.     CloseWindow(tempWind);
  316.     }
  317. } /* InitMac */
  318.  
  319. /* ================================= */
  320. OSErr    MissedRequiredParameters(AppleEvent* theAppleEvent)
  321. {
  322.     /* This is a general use routine to see if a handler missed any */
  323.     /*    required parameters                                         */
  324.     
  325.     OSErr        theErr;
  326.     Size        actualSize;
  327.     DescType    returnedType;
  328.     
  329.     /* note that the buffer is nil, and the size we request is zero */
  330.     theErr = AEGetAttributePtr(theAppleEvent,keyMissedKeywordAttr,
  331.                 typeWildCard,&returnedType,nil,0,&actualSize);
  332.                 
  333.     /* we are ok "if" we don't have any more parameters! */
  334.     if (theErr == errAEDescNotFound) return noErr;            /* desired results */
  335.     else if (theErr == noErr) return errAEEventNotHandled;    /* more stuff found */
  336.     else return theErr;                                        /* something else happened */
  337. } /* MissedRequiredParameters */
  338.  
  339. /* ================================= */
  340. extern     pascal    OSErr    doAEQuit(AppleEvent* theAppleEvent,AppleEvent* theReply,long handlerRefcon)
  341. {    
  342.     /* Quit Handler for AEs */
  343.     OSErr    result = 0;
  344.  
  345.     /* make sure we have all our required parameters */
  346.     
  347.     result = MissedRequiredParameters(theAppleEvent);
  348.     if (result == noErr)            
  349.     {
  350.         /* NOTE: if you want to call a routine to double check with the user do it here */
  351.         gFinished = true;
  352.         return result;
  353.     } /* if */
  354. } /* doAEQuit */
  355.  
  356.  
  357. /* ================================= */
  358. extern    pascal    OSErr doAENew(AppleEvent* theAppleEvent, AppleEvent* theReply, long handlerRefcon)
  359. {    
  360.     /* New window handler for AEs */
  361.     OSErr    result = 0;
  362.  
  363.     /* make sure we have all our required parameters */
  364.     
  365.     result = MissedRequiredParameters(theAppleEvent);
  366.     if (result == noErr)            
  367.     {
  368.         /* DoStuffHere */
  369.         if (gWindow == nil) 
  370.         {
  371.             DoNewWindow();            
  372.         }
  373.         
  374.         return result;
  375.     } /* if */
  376. } /* doAENew */
  377.  
  378. /* ================================= */
  379. extern    pascal    OSErr doAEClose(AppleEvent* theAppleEvent, AppleEvent* theReply, long handlerRefcon)
  380. {    
  381.     /* Close window handler for AEs */
  382.     OSErr    result = 0;
  383.  
  384.     /* make sure we have all our required parameters */
  385.     
  386.     result = MissedRequiredParameters(theAppleEvent);
  387.     if (result == noErr)            
  388.     {
  389.         /* DoStuffHere */
  390.         if (gWindow != nil) 
  391.             DoCloseWindow();
  392.         
  393.         return result;
  394.     } /* if */
  395. } /* doAEClose */
  396.  
  397. /* ================================= */
  398. extern    pascal    OSErr doAEAbout(AppleEvent* theAppleEvent, AppleEvent* theReply, long handlerRefcon)
  399. {
  400.     doAboutBox();
  401. } /* doAEAbout */
  402.  
  403.  
  404. /* ================================= */
  405. void    DoCloseWindow(void)
  406. {
  407.     if (gWindow != nil)
  408.     {
  409.         CloseWindow(gWindow);
  410.         gWindow = nil;
  411.         DisableItem(FileMenu,cCloseItem);
  412.         EnableItem(FileMenu,cNewItem);
  413.         
  414.         /* this is only because we are sending from out own application, normally the 
  415.             sending app handles this stuff */
  416.         if (gHasAppleEvents)
  417.         {
  418.         DisableItem(SpecialMenu,cSendCloseItem);
  419.         EnableItem(SpecialMenu,cSendNewItem);
  420.         }
  421.         
  422.         FixCursor();
  423.     } /* if */
  424.  
  425. } /* DoCloseWindow */
  426.  
  427.  
  428.  
  429. /* ================================= */
  430. void DoMenu(EventRecord* theEvent,WindowPtr whichWindow,long selection)
  431. {    
  432.     short    theMenu;
  433.     short    theItem;
  434.     static    Str255    theName;
  435.     short    trash;
  436.     
  437.     theMenu = HiWord(selection);
  438.     theItem = LoWord(selection);
  439.     
  440.     switch (theMenu) {    
  441.         case kAppleMenuID:
  442.             {    if (theItem == cAboutItem)
  443.                     doAboutBox();
  444.                 else {
  445.                     GetItem(AppleMenu,theItem,theName);
  446.                     trash = OpenDeskAcc(theName);
  447.                     }
  448.                 break;
  449.             }
  450.         case kFileMenuID: 
  451.             switch (theItem) {
  452.                 case cNewItem:
  453.                     DoNewWindow();
  454.                     break;
  455.                 case cCloseItem:
  456.                     DoCloseWindow();
  457.                     break;
  458.                 case cQuitItem:
  459.                     gFinished = true;
  460.                 }
  461.             break;
  462.         case kEditMenuID:
  463.             break;
  464.         case kSpecialMenuID:
  465.                 switch (theItem) {
  466.                 case cSendQuitItem:
  467.                     SendQuit();
  468.                     break;
  469.                 case cSendNewItem:
  470.                     SendNew();
  471.                     break;
  472.                 case cSendCloseItem:
  473.                     SendClose();
  474.                     break;
  475.                 case cSendAboutItem:
  476.                     SendAbout();
  477.                     break;
  478.                 case cSendAboutToFinder:
  479.                     SendAboutToFinder();
  480.                     break;
  481.                 case cSendEmptyTrashToFinder:
  482.                     SendEmptyTrashToFinder();
  483.                     break;
  484.                 }
  485.             break;
  486.     
  487.     } /* switch */
  488.     HiliteMenu(0);
  489.     
  490. }    /* DoMenu */
  491.  
  492.  
  493.  
  494.  
  495. /* ================================= */
  496. void DoMouseDown(EventRecord* theEvent)
  497. {
  498.     WindowPtr    whichWindow;
  499.     long        selection;
  500.     Rect        dragLimit;
  501.     GDHandle    theGDHandle     = nil;
  502.     Rect        tempRect;
  503.     GrafPtr        oldPort = nil;
  504.     Point        thePt;
  505.  
  506.     /* calculate a limit for dragging on this mouse click */
  507.     if (gHasColor) {    
  508.         theGDHandle = GetGDevice();
  509.         dragLimit = (**theGDHandle).gdRect;
  510.         } /* if */
  511.     else {
  512.         dragLimit = screenBits.bounds;
  513.         } /* else */
  514.         
  515.         
  516.     switch (FindWindow(theEvent->where,&whichWindow)) {
  517.         case inDesk:
  518.             break;
  519.         case inMenuBar:
  520.             selection = MenuSelect(theEvent->where);
  521.             DoMenu(theEvent, whichWindow, selection);
  522.             break;
  523.         case inSysWindow:
  524.             SystemEvent(theEvent);
  525.             break;
  526.         case inContent:
  527.             {
  528.                 /* Flash the rectangle, just to show we are there */
  529.                 GetPort(&oldPort);
  530.                 SetPort(whichWindow);
  531.                 tempRect = whichWindow->portRect;
  532.                 tempRect.right -= 16;
  533.                 tempRect.bottom -= 16;
  534.                 thePt = theEvent->where;
  535.                 GlobalToLocal(&thePt);
  536.                 if (PtInRect(thePt,&tempRect))
  537.                 {
  538.                     InvertRect(&tempRect);
  539.                     InvertRect(&tempRect);
  540.                 }
  541.                 SetPort(oldPort);
  542.             }
  543.             break;
  544.         case inDrag: 
  545.             InsetRect(&dragLimit,4,4);
  546.             dragLimit.top = dragLimit.top + GetMBarHeight();
  547.             DragWindow(whichWindow,theEvent->where,&dragLimit);
  548.             FixCursor();
  549.             break;
  550.         case inGrow:
  551.             {
  552.             tempRect.top = 40;
  553.             tempRect.left = 40;
  554.             tempRect.bottom = (4 + dragLimit.bottom-dragLimit.top);
  555.             tempRect.right = (dragLimit.right-dragLimit.left + 4);
  556.             selection = GrowWindow(whichWindow,theEvent->where,&tempRect);
  557.             SizeWindow(whichWindow,LoWord(selection),HiWord(selection),true);
  558.             
  559.             tempRect = whichWindow->portRect;
  560.             GetPort(&oldPort);
  561.             SetPort(whichWindow);
  562.             InvalRect(&tempRect);
  563.             SetPort(oldPort);
  564.             FixCursor();
  565.             }
  566.             break;
  567.             
  568.         case inGoAway:
  569.             if (TrackGoAway(whichWindow,theEvent->where))
  570.                 DoCloseWindow();
  571.             break;
  572.         case inZoomIn:
  573.             if (TrackBox(whichWindow,theEvent->where,inZoomIn)) 
  574.             {
  575.                 GetPort(&oldPort);
  576.                 SetPort(whichWindow);
  577.                 EraseRect(&(whichWindow->portRect));
  578.                 ZoomWindow(whichWindow,inZoomIn,true);
  579.                 SetPort(oldPort);
  580.                 FixCursor();
  581.             }
  582.             break;
  583.         case inZoomOut:
  584.             if (TrackBox(whichWindow,theEvent->where,inZoomOut)) 
  585.             {
  586.                 GetPort(&oldPort);
  587.                 SetPort(whichWindow);
  588.                 EraseRect(&(whichWindow->portRect));
  589.                 ZoomWindow(whichWindow,inZoomOut,true);
  590.                 SetPort(oldPort);
  591.                 FixCursor();
  592.             }
  593.             break;
  594.     } /* switch FindWindow */
  595. } /* DoMouseDown */
  596.  
  597.  
  598. /* ================================= */
  599. void DoKey(EventRecord* theEvent)
  600. {    
  601.     char    theKey;
  602.     long    selection;
  603.     
  604.     /* is the cmd key down? */
  605.     theKey = charCodeMask & theEvent->message;
  606.     if (cmdKey & theEvent->modifiers) {
  607.         selection = MenuKey(theKey);
  608.         DoMenu(theEvent,FrontWindow(),selection);
  609.         } /* if */
  610.     else;
  611.     
  612.     
  613. } /* DoKey */
  614.  
  615.  
  616. /* ================================= */
  617. void    DoNewWindow(void)
  618. {
  619.     Str255    theName = "\p<Untitled>";
  620.     
  621.     gWindow = GetNewWindow(kWindTemplateID,&gWStorage,(WindowPtr)-1L);
  622.     SetWTitle(gWindow,theName);
  623.     ShowWindow(gWindow);
  624.     DisableItem(FileMenu,cNewItem);
  625.     EnableItem(FileMenu,cCloseItem);
  626.     /* this is only because we are sending from out own application, normally the 
  627.         sending app handles this stuff */
  628.     if (gHasAppleEvents)
  629.     {
  630.         EnableItem(SpecialMenu,cSendCloseItem);
  631.         DisableItem(SpecialMenu,cSendNewItem);
  632.     }
  633.     
  634.     FixCursor();
  635.  
  636. }    /* DoNewWindow */
  637.  
  638.  
  639.  
  640. /* ================================= */
  641. void DoUpdate(EventRecord* theEvent)
  642. {
  643.     WindowPtr     whichWindow;
  644.     GrafPtr        oldPort;
  645.     Rect        contentRect;
  646.     
  647.     whichWindow = (WindowPtr)theEvent->message;
  648.     GetPort(&oldPort);
  649.     BeginUpdate(whichWindow);
  650.     SetPort(whichWindow);
  651.     
  652.     /* do the real drawing here */
  653.     
  654.     PenSize(3,3);
  655.     contentRect = whichWindow->portRect;
  656.     /* make sure we redraw the scroll bars */
  657.     EraseRect(&contentRect);
  658.     /* now only draw in the real content area */
  659.     contentRect.right -= 18;
  660.     contentRect.bottom -= 18;
  661.     DrawGrowIcon(whichWindow);
  662.     ForeColor(redColor);
  663.     MoveTo(contentRect.left,contentRect.top);
  664.     /* is there a C equiv to "with" ? */
  665.     LineTo(contentRect.right,contentRect.bottom);
  666.     MoveTo(contentRect.right,contentRect.top);
  667.     LineTo(contentRect.left, contentRect.bottom);
  668.     
  669.     /* clean up */
  670.     ForeColor(blackColor);
  671.     PenNormal();
  672.     EndUpdate(whichWindow);
  673.     SetPort(oldPort);
  674.  
  675. } /* DoUpdate */
  676.  
  677.  
  678. /* ================================= */
  679. void    DoOSEvent(EventRecord* theEvent)
  680. {
  681.     int    highByte;
  682.     
  683.     /* sign extended shift */
  684.     highByte = theEvent->message >> 24;
  685.     /* mask off the high bits */
  686.     highByte &= 0x00FF;
  687.     
  688.     if (highByte == suspendResumeMessage)
  689.     {
  690.         if (theEvent->message & resumeFlag)
  691.             { /* resuming */
  692.                 if (theEvent->message & convertClipboardFlag) {;}
  693.                     /* if we wanted the clipboard, we would grab it here */
  694.                 else {;}
  695.                     /* resume without converting */
  696.                 
  697.                 /* save time and do your activate stuff from here */
  698.                 gInForeground = true;
  699.             }
  700.             else /* suspend event */
  701.             {
  702.                 gInForeground = false;
  703.  
  704.                 /* convert the clipboard here */
  705.                 /* save time and do your deactivate stuff from here */
  706.             }
  707.     } /* suspend/resume event */
  708.     else if (highByte == mouseMovedMessage)
  709.     {
  710.         /* check if we are still over the content area of our window */
  711.         if (PtInRgn(theEvent->where,gMouseMovedRgn))
  712.         {
  713.             /* we are still in the content region */
  714.             ;
  715.         }
  716.         else /* recalculate the region */
  717.         {
  718.             FixCursor();
  719.         }
  720.     } /* mouse moved */
  721. } /* DoOSEvent */
  722.  
  723.  
  724. /* ================================= */
  725. void    SetUpperCorner(Rect* theRect,Point aPt)
  726. {
  727.     theRect->top = aPt.v;
  728.     theRect->left = aPt.h;
  729.     
  730. } /* SetUpperCorner */
  731.  
  732.  
  733. /* ================================= */
  734. void    GetUpperCorner(Rect* theRect,Point* aPt)
  735. {
  736.     aPt->h = theRect->left;
  737.     aPt->v = theRect->top;
  738.     
  739. } /* GetUpperCorner */
  740.  
  741.  
  742. /* ================================= */
  743. void    GetLowerCorner(Rect* theRect,Point* aPt)
  744. {
  745.     aPt->h = theRect->right;
  746.     aPt->v = theRect->bottom;
  747.  
  748. } /* SetLowerCorner */
  749.  
  750.  
  751. /* ================================= */
  752. void    SetLowerCorner(Rect* theRect,Point aPt)
  753. {
  754.     theRect->bottom = aPt.v;
  755.     theRect->right = aPt.h;
  756.     
  757. } /* SetLowerCorner */
  758.  
  759.  
  760. /* ================================= */
  761. void    SendCoreEvent(AEEventID theAEEventID)
  762. {
  763.     ProcessSerialNumber theProcSerialNum;
  764.     AEAddressDesc        theTargetAddress;
  765.     OSErr                theErr;
  766.   
  767.       /* first create the target... me */
  768.     theProcSerialNum.highLongOfPSN = 0;
  769.     theProcSerialNum.lowLongOfPSN = kCurrentProcess;
  770.     theErr = AECreateDesc(typeProcessSerialNumber, (Ptr)&theProcSerialNum, sizeof(theProcSerialNum),
  771.         &theTargetAddress);
  772.         
  773.     SendEvent(kCoreEventClass,theAEEventID,&theTargetAddress);
  774. } /* SendCoreEvent */
  775.  
  776.  
  777. /* ================================= */
  778. void    SendFndrEvent(AEEventID theAEEventID)
  779. {
  780.     OSType            FndrType = 'MACS';
  781.     OSErr            theErr;
  782.     AEAddressDesc    theTargetAddress;
  783.     Str255            errMsg = "\pProblem creating the target desc";
  784.  
  785.     /* first create the target descriptor... the Finder */
  786.         
  787.     theErr = AECreateDesc(typeProcessSerialNumber, (Ptr)&gFinderPSN, sizeof(gFinderPSN),
  788.         &theTargetAddress);
  789.         
  790. // #ifdef NOBROWSER
  791.  
  792.     { /* if you wanted to use the FINDER's application signature instead of the PPC browser
  793.         you could use this code instead of the Finder's process serial number */
  794.     OSType    theSignature = 'MACS';
  795.     
  796.     theErr = AECreateDesc(typeApplSignature, (Ptr)&FndrType, sizeof(FndrType),
  797.         &theTargetAddress);
  798.     if (theErr) ErrorAlert((ConstStr255Param)&"\pCould not create target addr from Sig",theErr);
  799.     }
  800.     
  801.     { /* if you need to send out info over the network this is how you do it */
  802.     theErr = AECreateDesc(typeTargetID, (Ptr)&gFinderTargetID, sizeof(gFinderTargetID),
  803.         &theTargetAddress);
  804.     }
  805. // #endif
  806.  
  807.     if (theErr != noErr) ErrorAlert((ConstStr255Param)&errMsg,theErr);
  808.     if (theAEEventID == 'empt')
  809.         SendEvent(kFndrEventClass, theAEEventID, &theTargetAddress);
  810.     if (theAEEventID == 'abou')
  811.         SendEvent(kCoreEventClass, theAEEventID, &theTargetAddress);
  812.     
  813. }
  814.  
  815.  
  816. /* ================================= */
  817. void    SendQuit(void)
  818. {
  819.     SendCoreEvent(kAEQuitApplication);
  820. } /* SendQuit */
  821.  
  822.  
  823. /* ================================= */
  824. void SendNew(void)
  825. {
  826.     SendCoreEvent(kAENewWindow);
  827. } /* SendNew */
  828.  
  829.  
  830. /* ================================= */
  831. void SendClose(void)
  832. {
  833.     SendCoreEvent(kAECloseWindow);
  834. } /* SendClose */
  835.  
  836.  
  837. /* ================================= */
  838. void SendAbout(void)
  839. {
  840.     SendCoreEvent(kAEAbout);
  841. } /* SendAbout */
  842.  
  843.  
  844. /* ================================= */
  845. void SendAboutToFinder(void)
  846. {
  847.     SendFndrEvent(kAEAbout);
  848. } /* SendAboutToFinder */
  849.  
  850.  
  851. /* ================================= */
  852. void SendEmptyTrashToFinder(void)
  853. {
  854.     SendFndrEvent(kAEEmptyTrash);
  855. }
  856.  
  857.  
  858. /* ================================= */
  859. void    SendEvent(AEEventClass theAEEventClass, AEEventID theAEEventID,
  860.                   AEAddressDesc* theTargetAddressPtr)
  861. {
  862.     OSErr                theErr = 0;
  863.     AppleEvent            theAppleEvent, theAEReply;
  864.     Str255                ErrMsg = "\pSend Failed, Error #";
  865.     
  866.         
  867.     theErr = AECreateAppleEvent(theAEEventClass,theAEEventID,
  868.             theTargetAddressPtr,kAutoGenerateReturnID,
  869.             kAnyTransactionID,&theAppleEvent);
  870.         
  871.     /* no direct parameters so this one is easy */
  872.     
  873.     /* send it! */
  874.     theErr = AESend(&theAppleEvent,&theAEReply, kAENoReply, kAENormalPriority,
  875.         kAEDefaultTimeout,nil,nil);
  876.         
  877.     /* an IMPORTANT note: we are using kAEDefaultTimeout, but if we chose
  878.         kWaitReply and we are sending to ourselves, we would be waiting a 
  879.         long long time (like forever) since we can't reply until we check 
  880.         the event loop, and we don't check the event loop until we get a 
  881.         reply.  Notice a problem?  Use a direct send instead */
  882.         
  883.     if (theErr != noErr) 
  884.         ErrorAlert((ConstStr255Param)&ErrMsg,theErr);
  885. } /* SendCoreEvent */
  886.  
  887.  
  888.  
  889. /* ================================= */
  890. void ErrorAlert(ConstStr255Param theString,OSErr theErr)
  891. {
  892.     Str255        *theErrStr, *theErrNumStr;
  893.     
  894.     Str255    stringStorage1, stringStorage2;
  895.     
  896.     theErrStr = &stringStorage1;
  897.     theErrNumStr = &stringStorage2;
  898.  
  899.     theErrStr = &"\p";
  900.     theErrNumStr = &"\p";
  901.     
  902.     switch (theErr)
  903.     {
  904.     case (-609):
  905.         theErrStr =  &"\pconnectionInvalid";
  906.         break;
  907.     case (-910):
  908.         theErrStr = &"\pport is already open, maybe in another application";
  909.         break;
  910.     case (-913):
  911.         theErrStr = &"\pPPCPortRec  is bad (malformed)";    
  912.         break;
  913.     case (-930):
  914.         theErrStr = &"\pbadServiceMethodErr, illegal service type, or not supported";
  915.         break;
  916.     case (-1700):
  917.         theErrStr = &"\perrAECoercionFail";
  918.         break;
  919.     case (-1701):
  920.          theErrStr = &"\perrAEDescNotFound";
  921.          break;
  922.      case (-1702):
  923.         theErrStr = &"\perrAECorruptData";
  924.          break;
  925.     case (-1703):
  926.         theErrStr = &"\perrAEWrongDataType";
  927.          break;
  928.     case (-1704):
  929.         theErrStr = &"\perrAENotAEDesc";
  930.          break;
  931.     case (-1708):    
  932.         theErrStr = &"\perrAEEventNotHandled";
  933.         break;
  934.     case (-1709):
  935.         theErrStr = &"\perrAEReplyNotValid";
  936.         break;
  937.     case (-1710):
  938.         theErrStr = &"\perrAEUnknownSendMode";
  939.         break;
  940.     case (-1711):
  941.         theErrStr = &"\perrAEWaitCanceled";         
  942.         break;
  943.     case (-1712):
  944.         theErrStr = &"\perrAETimeout";         
  945.         break;
  946.     case (-1713):
  947.         theErrStr = &"\perrAENoUserInteraction";   
  948.         break;
  949.     case (-1714):
  950.         theErrStr = &"\perrAENotASpecialFunction";
  951.         break;
  952.     case (-1715):
  953.         theErrStr = &"\perrAEParamMissed"; 
  954.         break;
  955.     case (-1716):
  956.         theErrStr = &"\perrAEUnknownAddressType";
  957.         break;
  958.     case (-1717):  
  959.         theErrStr = &"\perrAEHandlerNotFound";
  960.         break;
  961.     case (-1718): 
  962.         theErrStr = &"\perrAEReplyNotArrived";
  963.         break;
  964.     case (-1719):
  965.         theErrStr = &"\perrAEIllegalIndex";   
  966.         break;   
  967.     default:
  968.         NumToString(theErr, theErrNumStr);
  969.     } /* switch */
  970.     
  971.     ParamText(theString,(ConstStr255Param)theErrStr,
  972.             (ConstStr255Param)theErrNumStr,(ConstStr255Param)"\p");
  973.     CautionAlert(kErrorAlertID,nil);
  974. } /* ErrorAlert */
  975.  
  976.  
  977.  
  978.  
  979. /* ================================= */
  980. void    FixCursor(void)
  981. {
  982.     Point    where, aPt;
  983.     Rect    theRect;
  984.     GrafPtr    oldPort;
  985.     
  986.     GetMouse(&where); /* if this is an event you can also use event.where */
  987.     if ((gWindow != nil) && (gInForeground))
  988.         { 
  989. //        GetPort(&oldPort);
  990. //        SetPort(gWindow);
  991.         
  992.         
  993.         theRect = (**(((WindowPeek)gWindow)->contRgn)).rgnBBox;
  994.  
  995.         /* adjust for the scroll bars */
  996.         theRect.right -= 16;
  997.         theRect.bottom -= 16;
  998.         
  999.         /* divide the world into two parts, us and them */
  1000.         RectRgn(gMainContentRgn, &theRect);
  1001.         RectRgn(gAllElseRgn, &(screenBits.bounds));
  1002.         UnionRgn(gAllElseRgn,GetGrayRgn(),gAllElseRgn);
  1003.         DiffRgn(gAllElseRgn, gMainContentRgn, gAllElseRgn);
  1004.         
  1005.         if (PtInRect(where,&theRect))
  1006.             {
  1007.                 gMouseMovedRgn = gMainContentRgn;
  1008.                 SetCursor(*gPlusCursor);
  1009.             }
  1010.             else
  1011.             {
  1012.                 gMouseMovedRgn = gAllElseRgn;
  1013.                 InitCursor();
  1014.             }
  1015. //        SetPort(oldPort);
  1016.         }
  1017.     else 
  1018.         { /* there is no winodow */
  1019.         InitCursor();
  1020.         RectRgn(gAllElseRgn,&(screenBits.bounds));
  1021.         UnionRgn(GetGrayRgn(),gAllElseRgn,gAllElseRgn);
  1022.         EmptyRgn(gMainContentRgn);
  1023.         gMouseMovedRgn = gAllElseRgn;
  1024.         }
  1025.  
  1026. } /* FixCursor */
  1027.  
  1028.  
  1029. /* ================================= */
  1030. void    Loop(void)
  1031. {
  1032.     EventRecord    theEvent;
  1033.     FixCursor();
  1034.     
  1035.     do {
  1036.     if (WaitNextEvent(everyEvent,&theEvent,15,gMouseMovedRgn))
  1037.     {
  1038.         switch (theEvent.what) {
  1039.         case mouseDown:
  1040.             DoMouseDown(&theEvent);
  1041.             break;
  1042.         case mouseUp:
  1043.             break;
  1044.         case keyDown:
  1045.         case autoKey:
  1046.             DoKey(&theEvent);
  1047.             break;
  1048.         case diskEvt:
  1049.             break;
  1050.         case activateEvt:
  1051.             break;
  1052.         case updateEvt:
  1053.             DoUpdate(&theEvent);            
  1054.             break;
  1055.         case osEvt:
  1056.             DoOSEvent(&theEvent);
  1057.             break;
  1058.         case kHighLevelEvent:
  1059.             if (gHasAppleEvents) AEProcessAppleEvent(&theEvent);
  1060.             break;
  1061.         
  1062.         } /* switch */
  1063.     } /* end if WaitNextEvent */
  1064.     
  1065.         
  1066.     } while (!gFinished);
  1067.     
  1068.     
  1069. } /* Loop */
  1070.  
  1071.  
  1072. /* ================================= */
  1073. void SetUpMenus(void)
  1074. {
  1075.     /* create some menus from the menu resources */
  1076.     AppleMenu = GetMenu(kAppleMenuID);
  1077.     FileMenu = GetMenu(kFileMenuID);
  1078.     EditMenu = GetMenu(kEditMenuID);
  1079.     SpecialMenu = GetMenu(kSpecialMenuID);
  1080.     
  1081.     AddResMenu(AppleMenu,'DRVR');
  1082.      
  1083.     InsertMenu(AppleMenu,0);
  1084.     InsertMenu(FileMenu,0);
  1085.     InsertMenu(EditMenu,0);
  1086.     if (gHasAppleEvents)
  1087.         InsertMenu(SpecialMenu,0);
  1088.     
  1089.     DrawMenuBar();
  1090.     
  1091.  
  1092. } /* SetUpMenus */
  1093.  
  1094.  
  1095. /* ================================= */
  1096. void    doAboutBox(void)
  1097. {
  1098.     OSErr    theErr;
  1099.     theErr = Alert(kAboutBoxID,nil);
  1100.     
  1101. } /* doAboutBox */
  1102.     
  1103.     
  1104.  
  1105. /* ================================= */
  1106. void    main(void)
  1107. {
  1108.     InitMac(8);
  1109.     SetUpMenus();
  1110.     ConnectToFinder();
  1111.     Loop();
  1112.     DisconnectFromFinder();
  1113. } /* main() */
  1114.  
  1115.